package rhc.discribute.util;

import java.util.Date;

import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;

import rhc.discribute.util.ScheduleUpdate.ScheduleType;

/**
 * 定时更新执行任务类
 * 
 * @author rhc
 *
 */
public class ScheduleUpdateUtil {

	/**
	 * 调度器工厂
	 */
	private final static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();

	static {
		SystemCloseHookUtil.addSystemCloseHook(new Runnable() {

			@Override
			public void run() {
				try {
					for (Scheduler s : gSchedulerFactory.getAllSchedulers()) {
						s.shutdown();
					}
				} catch (SchedulerException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

		});
	}

	/**
	 * 运行一个job
	 * 
	 * @param update
	 */
	public static void runJob(ScheduleUpdate update) {

		JobDetail job = getJob(update);
		Trigger trigger = getTrigger(update);

		runJob(job, trigger);
	}

	/**
	 * 停止一个job
	 * 
	 * @param update
	 */
	public static void stopJob(ScheduleUpdate update) {

		String name = getName(update, "job");
		String group = getGroup(update);

		pauseJob(name, group);

	}

	/**
	 * 删除一个job
	 * 
	 * @param update
	 */
	public static void removeJob(ScheduleUpdate update) {

		String name = getName(update, "job");
		String group = getGroup(update);

		removeJob(name, group);
	}

	/**
	 * 重新启动一个job
	 * 
	 * @param update
	 */
	public static void againStartJob(ScheduleUpdate update) {

		removeJob(update);
		runJob(update);

	}

	/**
	 * 运行job
	 * 
	 * @param job
	 */
	private static void runJob(JobDetail job, Trigger trigger) {

		try {
			Scheduler sched = gSchedulerFactory.getScheduler();

			sched.scheduleJob(job, trigger);

			if (!sched.isStarted()) {
				sched.start();
			}

		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * 获取job
	 * 
	 * @param update
	 * @return
	 * @throws SchedulerException
	 */
	private static JobDetail getJob(ScheduleUpdate update) {

		String name = getName(update, "job");
		String group = getGroup(update);
		JobDataMap map = new JobDataMap();
		map.put(ScheduleUpdate.SCHEDULE_UPDATE, update);
		JobDetail job = JobBuilder.newJob(update.getJobClass()).withIdentity(name, group).setJobData(map).build();

		return job;
	}

	/**
	 * 获取trigger
	 * 
	 * @param update
	 * @return
	 */
	private static Trigger getTrigger(ScheduleUpdate update) {

		ScheduleUpdate.ScheduleType scheduleType = update.getScheduleType();
		String name = getName(update, "trigger");
		String group = getGroup(update);
		int interval = update.getTimeInterval();
		String cron = update.getCron();
		Trigger trigger = null;
		if (scheduleType.equals(ScheduleType.TIMEINTERVAL)) {
			SimpleScheduleBuilder schedule = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(interval);
			if (update.isForever()) {
				schedule.repeatForever();
			} else {
				int runCount = update.runCount();
				if (runCount < 1) {
					throw new IllegalArgumentException("运行次数不能小于1");
				}
				schedule.withRepeatCount(runCount);
			}
			TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger().withIdentity(name, group)
					.withSchedule(schedule);
			if (update.startNow()) {
				triggerBuilder=triggerBuilder.startNow();
			} else{
				long currentMilis=System.currentTimeMillis();
				long startMilis=currentMilis+interval*1000;
				triggerBuilder=triggerBuilder.startAt(new Date(startMilis));
			}
			trigger = triggerBuilder.build();
		} else if (scheduleType.equals(ScheduleType.CRON)) {
			TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger().withIdentity(name, group)
					.withSchedule(CronScheduleBuilder.cronSchedule(cron));
			if (update.startNow()) {
				triggerBuilder = triggerBuilder.startNow();
			}
			trigger = triggerBuilder.build();
		}

		return trigger;
	}

	/**
	 * 暂停一个job
	 * 
	 * @param name
	 * @param group
	 */
	private static void pauseJob(String name, String group) {
		try {
			Scheduler sched = gSchedulerFactory.getScheduler();

			sched.pauseJob(JobKey.jobKey(name, group));
			sched.pauseTrigger(TriggerKey.triggerKey(name, group));
		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 删除一个job
	 * 
	 * @param name
	 * @param group
	 */
	private static void removeJob(String name, String group) {
		try {
			Scheduler sched = gSchedulerFactory.getScheduler();
			sched.pauseJob(JobKey.jobKey(name, group));
			sched.unscheduleJob(TriggerKey.triggerKey(name, group));
			sched.deleteJob(JobKey.jobKey(name, group));
		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 获取job名
	 * 
	 * @param update
	 * @return
	 */
	private static String getName(ScheduleUpdate update, String type) {
		return update.getId() + type;
	}

	/**
	 * 获取job分组
	 * 
	 * @param update
	 * @return
	 */
	private static String getGroup(ScheduleUpdate update) {
		return update.getId();
	}
}
